﻿using System;
using System.Linq;
using System.Threading;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Collections.ObjectModel;
using Microsoft.SharePoint.Utilities;

namespace VIALUTIONS.InfoPath.FormsHub.InfoPathFormsHubWebPart
{
    /// <summary>
    /// The class WebPartProperties is based on
    /// the SPEditorPart and handles the configuration
    /// of the InfoPath forms.
    /// </summary>
    public class WebPartProperties : SPEditorPart
    {
        #region Fields

        private Collection<InfoPathForm> _allForms;

        private DropDownList _drpForms;
        private TextBox _editName;
        private TextBox _editSource;
        private CheckBox _checkDifferentTarget;
        private Label _labTarget;
        private TextBox _editTarget;

        #endregion 

        public WebPartProperties(string clientId, string title) : base(clientId, title){}

        #region ViewState

        /// <summary>
        /// Loads the collection of InfoPath forms
        /// configurations from the ViewState
        /// </summary>
        /// <param name="savedState">The ViewState</param>
        protected override void LoadViewState(object savedState)
        {
            base.LoadViewState(savedState);
            _allForms = (Collection<InfoPathForm>)ViewState["InfoPathForms"];
        }
        /// <summary>
        /// Saves the collection of InfoPath forms
        /// configurations to the ViewState
        /// </summary>
        /// <returns>The ViewState</returns>
        protected override object SaveViewState()
        {
            ViewState["InfoPathForms"] = _allForms;
            return base.SaveViewState();
        }

        #endregion

        /// <summary>
        /// Applies the changes made in the
        /// Edit Web Part section to the Web Part.
        /// </summary>
        /// <returns>A boolean signal for the result of this method</returns>
        public override bool ApplyChanges()
        {
            EnsureChildControls();

            var webPart = WebPartToEdit as InfoPathFormsHubWebPart;
            if (webPart != null) webPart.InfoPathForms = _allForms;

            return true;
        }
        /// <summary>
        /// Reads all neccessary information for 
        /// the Edit Web Part section from
        /// the Web Part. 
        /// </summary>
        public override void SyncChanges()
        {
            var webPart = WebPartToEdit as InfoPathFormsHubWebPart;

            if (webPart != null && webPart.InfoPathForms != null)
            {
                _allForms = webPart.InfoPathForms;
            }

            EnsureChildControls();
        }

        /// <summary>
        /// Method creates all html controls for
        /// the InfoPath Forms Hub category in
        /// the Edit Web Part section.
        /// </summary>
        protected override void CreateChildControls()
        {
            ChromeType = PartChromeType.None;
            base.CreateChildControls();

            ControlPanel.Controls.Add(new LiteralControl("<div class=\"ms-propGridTable\" id=\"" + ID + "\" style=\"display:;\">"));

            #region Headline

            ControlPanel.Controls.Add(new LiteralControl("<div class=\"UserSectionHead\">"));
            ControlPanel.Controls.Add(new Label { ToolTip = GetLocalizedText("resHeadConfigurationToolTip"), Text = GetLocalizedText("resHeadConfiguration") });
            ControlPanel.Controls.Add(new LiteralControl("</div>"));

            #endregion

            #region Table

            ControlPanel.Controls.Add(new LiteralControl("<div class=\"UserSectionBody\">"));
            ControlPanel.Controls.Add(CreateFormsTable());
            ControlPanel.Controls.Add(new LiteralControl("</div>"));

            #endregion

            #region Buttons

            var btnNewForm = new Button();
            var btnDelForm = new Button();

            btnNewForm.Text = GetLocalizedText("resButtonSave");
            btnNewForm.Style.Add(HtmlTextWriterStyle.Margin, "10px");
            btnNewForm.Click += BtnNewLibClick;

            btnDelForm.Text = GetLocalizedText("resButtonDelete");
            btnDelForm.Style.Add(HtmlTextWriterStyle.Margin, "10px");
            btnDelForm.Click += BtnDelFormClick;

            ControlPanel.Controls.Add(new LiteralControl("<div style=\"text-align:right;\">"));
            ControlPanel.Controls.Add(btnNewForm);
            ControlPanel.Controls.Add(btnDelForm);
            ControlPanel.Controls.Add(new LiteralControl("</div>"));

            #endregion

            ControlPanel.Controls.Add(new LiteralControl("</div>"));
        }

        /// <summary>
        /// Method creates a table containing a
        /// dropdown with all configured InfoPath
        /// forms and fields for adding new or
        /// changing existing entries.
        /// </summary>
        /// <returns>A html tabel element</returns>
        private Table CreateFormsTable()
        {
            var tableForms = new Table {Width = new Unit(100, UnitType.Percentage)};
            tableForms.Style.Add(HtmlTextWriterStyle.PaddingBottom, 10.ToString());

            #region Headline

            var headEdit = new Label { ToolTip = GetLocalizedText("resHeadSettingsToolTip"), Text = GetLocalizedText("resHeadSettings") };
            var rowHead = new TableRow();
            var cellHead = new TableCell();

            cellHead.Controls.Add(new LiteralControl("<div class=\"UserSectionHead\">"));
            cellHead.Controls.Add(headEdit);
            cellHead.Controls.Add(new LiteralControl("</div>"));
            rowHead.Cells.Add(cellHead);

            #endregion

            #region Name

            _editName = new TextBox
                            {
                                Height = new Unit(15, UnitType.Pixel),
                                Width = new Unit(100, UnitType.Percentage)
                            };

            var rowsName = new TableRow[2];
            rowsName[0] = new TableRow();
            rowsName[1] = new TableRow();

            var cellNameLabel = new TableCell();
            cellNameLabel.Controls.Add(new Label { Text = GetLocalizedText("resFormsName") });
            rowsName[0].Cells.Add(cellNameLabel);

            var cellNameText = new TableCell();
            cellNameText.Controls.Add(_editName);
            rowsName[1].Cells.Add(cellNameText);

            #endregion

            #region Source

            _editSource = new TextBox
                              {
                                  Height = new Unit(15, UnitType.Pixel),
                                  Width = new Unit(100, UnitType.Percentage)
                              };

            var rowsSource = new TableRow[2];
            rowsSource[0] = new TableRow();
            rowsSource[1] = new TableRow();

            var cellSourceLabel = new TableCell();
            cellSourceLabel.Controls.Add(new Label { Text = GetLocalizedText("resFormsSource") });
            rowsSource[0].Cells.Add(cellSourceLabel);

            var cellSourceText = new TableCell();
            cellSourceText.Controls.Add(_editSource);
            rowsSource[1].Cells.Add(cellSourceText);

            #endregion

            #region Target is Different

            _checkDifferentTarget = new CheckBox();
            _checkDifferentTarget.CheckedChanged += CheckDifferentTargetCheckedChanged;
            _checkDifferentTarget.AutoPostBack = true;

            var rowsTargetDiff = new TableRow[2];
            rowsTargetDiff[0] = new TableRow();
            rowsTargetDiff[1] = new TableRow();

            var cellTargetDiffLabel = new TableCell();
            cellTargetDiffLabel.Controls.Add(new Label { Text = GetLocalizedText("resFormsDifferentTarget") });
            rowsTargetDiff[0].Cells.Add(cellTargetDiffLabel);

            var cellTargetDiffText = new TableCell();
            cellTargetDiffText.Controls.Add(_checkDifferentTarget);
            rowsTargetDiff[1].Cells.Add(cellTargetDiffText);

            #endregion

            #region Target

            _editTarget = new TextBox
                              {
                                  Height = new Unit(15, UnitType.Pixel),
                                  Width = new Unit(100, UnitType.Percentage)
                              };

            _labTarget = new Label { Text = GetLocalizedText("resFormsTarget") };

            var rowsTarget = new TableRow[2];
            rowsTarget[0] = new TableRow();
            rowsTarget[1] = new TableRow();

            var cellTargetLabel = new TableCell();
            cellTargetLabel.Controls.Add(_labTarget);
            rowsTarget[0].Cells.Add(cellTargetLabel);

            var cellTargetText = new TableCell();
            cellTargetText.Controls.Add(_editTarget);
            rowsTarget[1].Cells.Add(cellTargetText);

            #endregion

            #region DropDown

            var rowsAll = new TableRow[2];
            rowsAll[0] = new TableRow();
            rowsAll[1] = new TableRow();

            var cellAllLabel = new TableCell();
            cellAllLabel.Controls.Add(new Label { Text = GetLocalizedText("resFormsList") });
            rowsAll[0].Cells.Add(cellAllLabel);

            var cellAllControl = new TableCell();
            _drpForms = new DropDownList { Width = new Unit(100, UnitType.Percentage) };
            _drpForms.SelectedIndexChanged += DrpFormsSelectedIndexChanged;
            _drpForms.AutoPostBack = true;

            if (_allForms != null && _allForms.Count > 0)
            {
                foreach (var item in _allForms)
                {
                    _drpForms.Items.Add(new ListItem(item.Name));
                }

                _editName.Text = _allForms[0].Name;
                _editSource.Text = _allForms[0].Source;
                _editTarget.Text = _allForms[0].Target;
                _checkDifferentTarget.Checked = !string.IsNullOrEmpty(_editTarget.Text);
            }

            _editTarget.Visible = _checkDifferentTarget.Checked;
            _labTarget.Visible = _checkDifferentTarget.Checked;

            cellAllControl.Controls.Add(_drpForms);
            rowsAll[1].Cells.Add(cellAllControl);

            #endregion

            #region Dotted Line 

            var rowLine = new TableRow();
            var cellLine = new TableCell();

            cellLine.Controls.Add(new LiteralControl("<div style='width:100%; margin-top:10px;' class='UserDottedLine'></div>"));
            cellLine.ColumnSpan = 2;

            rowLine.Cells.Add(cellLine);

            #endregion

            tableForms.Rows.AddRange(rowsAll);
            tableForms.Rows.Add(rowLine);
            tableForms.Rows.Add(rowHead);
            tableForms.Rows.AddRange(rowsName);
            tableForms.Rows.AddRange(rowsSource);
            tableForms.Rows.AddRange(rowsTargetDiff);
            tableForms.Rows.AddRange(rowsTarget);

            return tableForms;
        }
        /// <summary>
        /// Method is called to set all TextBoxes
        /// to the values of the selected InfoPath
        /// forms configuration.
        /// </summary>
        /// <param name="form">The selected InfoPath forms configuration</param>
        private void SetSelectedForm(InfoPathForm form)
        {
            _editName.Text = form.Name;
            _editSource.Text = form.Source;
            _checkDifferentTarget.Checked = false;
            _labTarget.Visible = false;
            _editTarget.Visible = false;

            if (string.IsNullOrEmpty(form.Target)) return;

            _checkDifferentTarget.Checked = true;
            _labTarget.Visible = true;
            _editTarget.Visible = true;
            _editTarget.Text = form.Target;
        }
        /// <summary>
        /// Gets the localized text from the
        /// resource files.
        /// </summary>
        /// <param name="resource">The name of the resource</param>
        /// <returns>Localized text</returns>
        private static string GetLocalizedText(string resource)
        {
            var lcid = Thread.CurrentThread.CurrentUICulture.LCID;

            return SPUtility.GetLocalizedString("$Resources: " + resource, "VIALUTIONS InfoPath Forms Hub\\InfoPath Forms Hub", (uint)lcid);
        }

        #region Events

        /// <summary>
        /// If the CheckBox is selected additional
        /// controls for configuration of a different
        /// save target get visible.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">Arguments for the event</param>
        void CheckDifferentTargetCheckedChanged(object sender, EventArgs e)
        {
            _labTarget.Visible = _checkDifferentTarget.Checked;
            _editTarget.Visible = _checkDifferentTarget.Checked;

            if(!_checkDifferentTarget.Checked)
            {
                _editTarget.Text = string.Empty;
            }
        }
        /// <summary>
        /// If the selected item in the DropDownBox changes
        /// all TextBoxes has to be set to the values of
        /// the selected InfoPath forms configuration.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">Arguments for the event</param>
        void DrpFormsSelectedIndexChanged(object sender, EventArgs e)
        {
            var drp = (DropDownList)sender;

            foreach (var item in _allForms.Where(item => item.Name.Equals(drp.SelectedValue)))
            {
                SetSelectedForm(item);
                return;
            }
        }
        /// <summary>
        /// If the Save Button is clicked it depends on the
        /// name of the selected InfoPath forms configuration
        /// if an update of that item is enforced or a new InfoPath
        /// forms configuration is created.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">Arguments for the event</param>
        void BtnNewLibClick(object sender, EventArgs e)
        {
            if (_allForms == null)
                _allForms = new Collection<InfoPathForm>();

            InfoPathForm form = null;

            //If form configuration already exists do just an update
            foreach (var item in _allForms.Where(item => item.Name.Equals(_editName.Text)))
            {
                form = item;

                form.Name = _editName.Text;
                form.Source = _editSource.Text;
                form.Target = _editTarget.Text;
            }

            //If form configuration don't exists create a new one
            if (form != null) return;
            form = new InfoPathForm { Name = _editName.Text, Source = _editSource.Text };

            if (_checkDifferentTarget.Checked)
            {
                form.Target = _editTarget.Text;
            }
            else
            {
                _editTarget.Text = string.Empty;
            }

            _allForms.Add(form);
            _drpForms.Items.Add(form.Name);
            _drpForms.SelectedIndex = _drpForms.Items.Count - 1;
        }
        /// <summary>
        /// On deleting an InfoPath forms configuration the
        /// item is removed from the DropDownBox and from
        /// the collection of all InfoPath forms configurations.
        /// </summary>
        /// <param name="sender">The sender of the event</param>
        /// <param name="e">Arguments for the event</param>
        void BtnDelFormClick(object sender, EventArgs e)
        {
            InfoPathForm delForm = null;

            foreach (var item in _allForms.Where(item => item.Name.Equals(_editName.Text)))
            {
                delForm = item;
            }

            if (delForm == null) return;

            _allForms.Remove(delForm);
            _drpForms.Items.Remove(delForm.Name);
            
            if (_drpForms.Items.Count > 0 && _allForms.Count > 0)
            {
                _drpForms.SelectedIndex = 0;
                SetSelectedForm(_allForms[0]);
            }
            else
            {
                _editName.Text = string.Empty;
                _editSource.Text = string.Empty;
                _editTarget.Text = string.Empty;
                _checkDifferentTarget.Checked = false;
                _labTarget.Visible = false;
                _editTarget.Visible = false;
            }
        }

        #endregion
    }
}
